"""
函数的定义与调用；
    1.定义函数的目的是封装代码的逻辑性，增加代码的可读性，创建与调用.
    2.函数的创建-def():
    3.用于处理各种序列类型的函数类型属于内置函数，而定义函数更能对于代码的重用
"""
def algerbra ():
    print('int')

algerbra()

def plus (a,b):
    print(a+b)

plus(11,22)
plus(22,33)

print('---------------------------------------------------------')

"""
函数的参数：
        1.pass,可以保证函数的完整性
        2.位置参数：
            有几个位置参数传递几个参数，一个传入参数对于def中的一个位置进行一一对应
        3.默认参数：
            a.若带有默认值的参数，在对该函数进行调用时，不必显示（不写入参数）参数传入给def中的函数，
            也就是说，def的定义函数会使用默认值进行返回
            b.def的位置参数若存在可变对象的话，则参数每执行一次就会储存一次，然后返回一次。
        4.关键字参数：
            a.在函数调用时指定参数名称，称为关键字参数，关键字参数必须在普通参数后面。
            b.命名关键字参数参时，等同于限制关键字形参，可以通过字符*来限制，对与限制关键字的形参，为了有利于后面参数的可读性，
            有助于跨版本的兼容
        5.可变参数；
            a.可变参数*，名为args,变量args指向tuple的对象，会自动收集所有未匹配的参数放到一个tuple中。
            b.可变参数**，名为kwargs，变量kwargs指向dict对象，会自动收集所有未匹配的参数放到一个dict中。
"""
def plus1 (a,b,c):
    print(a+b+c)

plus1(1,2,3)
plus1(11,22,33)
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
def plus2 (a=200,b=100):   #使用位置参数的默认值进行返回(默认参数)
    print(a+b)

plus2()                    #传入参数（未写入参数）为默认值
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
def plus3 (a=100,b=100):
    print(a+b)

plus3(111,222)             #若传递参数写入，则会对def-函数的位置参数进行依次更改,a=111,b=222
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
def vary (a,b=[]):      # 若存在可变变量，则变量值会储存覆盖
    b.append(a)         # 可以在def语句与append函数中间添加一条clear(),也能达到消除储存值的方法。
    print(b)

vary(100)
vary(200)
vary(300)
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
def vary1 (a,b=None):       #把b设置成一个默认参数
    if b is None:              #在def内定义一个列表，不会具有储存的功能
        b = []
        b.append(a)
        print(b)

vary1(100)
vary1(200)
vary1(300)
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
def keyword1 (a=100,b=200):
    print(a+b)

keyword1(a=300,b=100)        #关键字参数：a=300.b=100
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
def keyword2 (a,*,c):       #字符*号后面已经成为了关键字形参
    print(a)
    print(c)

keyword2(100,c=200)         #所以，参数c必须为关键字实参才能运行程序
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
def tuple (a,*args):
    print(a)
    print(args)
tuple(100,200,3000,4000,500)

def dict (a,**kwargs):
    print(a)
    print(kwargs)
dict(123,x='你',y='我')    #实参中的必须用关键传值

print('----------------------------------------------------')
print('#解包')
"""
参数的解包，对于数据容器进行分解传递，传入参数的实参中添加*变量，对序列中元素进行依次对内执行返回
"""
x = '123'
y = ['q','w','e']
z = ('r','t','y')
m = {'a':'Gracke','b':'big','c':'11:00'}
n = {11,22,33}
def bag1 (a,b,c):
    print(a)
    print(b)
    print(c)
bag1(*x)
bag1(*y)
bag1(*z)
bag1(*m)             #只返回键，不返回值
bag1(**m)            # 键的名称需要跟参数的名称一样且要一一对应，才能返回值，只返回值
bag1(*n)             # 先重新排序，后返回，集合的特点:可变性

print('----------------------------------------------------')

"""
参数解包与可变参数的嵌合使用
"""
def bag2 (a,*args):
    print(a)
    print(args)
bag2(10,(1,2,3))       # 前面没加*号，将元组(1,2,3)看成一个整体，进行实参传入def内
bag2(20,*(1,2,3))      # 传入参数的*号对元组进行解包，就是把实参的括号拆开，然后再传入到def内
bag2(30,*[1,2,3])      # 传入参数的*号对列表进行解包，就是把实参的中括号拆开，然后再传入到def内
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
dict_1 = {'姓名':'grack','爱好':'无'}
def bag3 (a,**kwargs):
    print(a)
    print(kwargs)
bag3(11,**dict_1)        #**可变参与*同理，**号将实参的括号拆开，然后传入到def内

print('----------------------------------------------------')

#综合运用
def summary (a,b=100,*args,**kwargs):
    print(a)
    print(b)
    print(args)
    for i in args:
        print(i)
    print(kwargs)       # kwargs将实参变成字典
    for key,valus in kwargs.items():        #字典需要通过内置函数items()才能遍历字典的键对值
        print(key)
        print(valus)

summary(10,100,1,2,3,4,x='ok',y='no')

print('------------------------------------------------------')

"""
返回关键字-return：
        1.数据可以通过return返回值，若不用则会返回None
        2.return返回函数
"""
def function1 (a,b):
    print(a+b)
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
r=function1(10,20)
print(r)            #不用返回None
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
def function2 (a,b):
    return a+b

r = function2(10,20)
print(r)
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
def function3():
    def func(x,y):
        return x*y
    return func     # 调用func 函数

r1 = function3()
r2 = r1(10,20)
print(r2)

